home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / QuickTime / QuickTime VR / Make QTVR Panorama / CApp.cp next >
Encoding:
Text File  |  2000-09-28  |  12.9 KB  |  569 lines  |  [TEXT/CWIE]

  1. /*
  2.     Make QTVR Panorama 1.0b1
  3.     
  4.     A simple PowerPlant application for processing PICT files into QuickTime VR™ movies.
  5.     
  6.     Created 29 Jan 1996 by EGH
  7.     
  8.     Copyright © 1996, Apple Computer, Inc. All rights reserved.
  9. */
  10.  
  11. #include <StandardFile.h>
  12.  
  13. #include <String_Utils.h>
  14. #include <LCaption.h>
  15. #include <UDesktop.h>
  16. #include <UDrawingState.h>
  17. #include <LEditField.h>
  18. #include <LGrowZone.h>
  19. #include <UMemoryMgr.h>
  20. #include <LPlaceHolder.h>
  21. #include <URegistrar.h>
  22. #include <LScroller.h>
  23. #include <LStdControl.h>
  24. #include <LTabGroup.h>
  25. #include <LTextEdit.h>
  26. #include <LUndoer.h>
  27. #include <LWindow.h>
  28. #include <PP_Resources.h>
  29.  
  30. #include "CApp.h"
  31.  
  32. #include "CBeachBall.h"
  33. #include "CMovieMaker.h"
  34. #include "CPict2VRWindow.h"
  35. #include "CPrefsWindow.h"
  36. #include "CUtils.h"
  37.  
  38. CPreferences *gAppPrefs = nil;
  39.  
  40. CApp *gApp = nil;
  41.  
  42. void main(void)
  43. {
  44.     SetDebugThrow_(debugAction_Alert);
  45.     SetDebugSignal_(debugAction_Alert);
  46.  
  47.     InitializeHeap(8);
  48.     UQDGlobals::InitializeToolbox(&qd);
  49.     
  50.         // check for the existence of QuickTime
  51.     Int32 result;
  52.     OSErr err = ::Gestalt(gestaltQuickTime, &result);
  53.     if (err != noErr)
  54.     {
  55.         ::StopAlert(ALRT_NoQT, nil);
  56.         ExitToShell();
  57.     }
  58.     
  59.     new LGrowZone(20000);
  60.     
  61.         // fire up QuickTime and load the components necessary for
  62.         // creating pano media
  63.     ::EnterMovies();
  64.     ::RegisterComponentResourceFile(CurResFile(), 0);
  65.     
  66.     CApp theApp;
  67.     gApp = &theApp;
  68.     theApp.Run();
  69.     
  70.     ::ExitMovies();
  71. }
  72.  
  73.  
  74. CApp::CApp()
  75. {
  76.     mDropMode = false;
  77.     
  78.         // Register classes for objects created from 'PPob' resources
  79.     URegistrar::RegisterClass(CPict2VRWindow::class_ID,    CPict2VRWindow::CreatePict2VRWindowWindowStream);
  80.     URegistrar::RegisterClass(CPrefsWindow::class_ID,    CPrefsWindow::CreatePrefsWindowWindowStream);
  81.  
  82.     URegistrar::RegisterClass(LCaption::class_ID,        LCaption::CreateCaptionStream);
  83.     URegistrar::RegisterClass(LDialogBox::class_ID,        LDialogBox::CreateDialogBoxStream);
  84.     URegistrar::RegisterClass(LEditField::class_ID,        LEditField::CreateEditFieldStream);
  85.     URegistrar::RegisterClass(LPicture::class_ID,        LPicture::CreatePictureStream);
  86.     URegistrar::RegisterClass(LPlaceHolder::class_ID,    LPlaceHolder::CreatePlaceHolderStream);
  87.     URegistrar::RegisterClass(LStdButton::class_ID,        LStdButton::CreateStdButtonStream);
  88.     URegistrar::RegisterClass(LStdCheckBox::class_ID,    LStdCheckBox::CreateStdCheckBoxStream);
  89.     URegistrar::RegisterClass(LStdControl::class_ID,    LStdControl::CreateStdControlStream);
  90.     URegistrar::RegisterClass(LStdPopupMenu::class_ID,    LStdPopupMenu::CreateStdPopupMenuStream);
  91.     URegistrar::RegisterClass(LStdRadioButton::class_ID,    LStdRadioButton::CreateStdRadioButtonStream);
  92.     URegistrar::RegisterClass(LTabGroup::class_ID,        LTabGroup::CreateTabGroupStream);
  93.     URegistrar::RegisterClass(LView::class_ID,            LView::CreateViewStream);
  94.     URegistrar::RegisterClass(LWindow::class_ID,        LWindow::CreateWindowStream);
  95.     
  96.         // create application preferences
  97.     Str63 appName;
  98.     ::GetIndString(appName, STRx_Standards, str_ProgramName);
  99.     gAppPrefs = new CPreferences('p2vr', Creator_, appName);
  100.     
  101.         // look for preferences and use them
  102.     mPrefsHdl = (P2VRPrefsHdl)gAppPrefs->GetPreferenceResource(ResType_Preferences, 128);
  103.     if (mPrefsHdl == nil)
  104.     {
  105.             // no prefs, so create default ones
  106.         mPrefsHdl = (P2VRPrefsHdl)::NewHandle(sizeof (P2VRPrefsRec));
  107.         if (mPrefsHdl != nil)
  108.         {
  109.             (*mPrefsHdl)->dropMode = mDropMode;
  110.             
  111.             (*mPrefsHdl)->width = 400;
  112.             (*mPrefsHdl)->height = 300;
  113.             (*mPrefsHdl)->codec = 'cvid';
  114.             (*mPrefsHdl)->pan = 0;
  115.             (*mPrefsHdl)->tilt = 0;
  116.             (*mPrefsHdl)->zoom = 0;
  117.             (*mPrefsHdl)->spatialQuality = codecHighQuality;
  118.             (*mPrefsHdl)->depth = 32;
  119.             CopyPStr("\p.tile", (*mPrefsHdl)->tileSuffix);
  120.             CopyPStr("\p.snm", (*mPrefsHdl)->movieSuffix);
  121.             
  122.             (*mPrefsHdl)->replaceFiles = false;
  123.         }
  124.     }
  125.     else
  126.     {
  127.         mDropMode = (*mPrefsHdl)->dropMode;
  128.     }
  129.     
  130.         // initialize spinning cursor
  131.     CBeachBall::InitBeachBall();
  132.     
  133.     if (!mDropMode)
  134.     {
  135.         try
  136.         {
  137.             LWindow *splash = LWindow::CreateWindow(WIND_Splash, this);
  138.             
  139.             if (splash != nil)
  140.             {
  141.                 splash->Show();
  142.                 splash->UpdatePort();
  143.                 UInt32 splashTime = ::TickCount() + 120; // this should be up for at least 180 ticks
  144.                 CBeachBall::StartSpinningTask(5);
  145.                 while (::TickCount() < splashTime) ;
  146.                 CBeachBall::StopSpinningTask();
  147.                 
  148.                 delete splash;
  149.             }
  150.         }
  151.         catch (...)
  152.         {
  153.             // fall out
  154.         }
  155.     }
  156. }
  157.  
  158.  
  159. CApp::~CApp()
  160. {
  161.         // save the preferences
  162.     if (gAppPrefs != nil && mPrefsHdl != nil)
  163.     {
  164.         (*mPrefsHdl)->dropMode = mDropMode;
  165.         gAppPrefs->SavePreferenceResource(ResType_Preferences, 128, (Handle)mPrefsHdl);
  166.     }
  167. }
  168.  
  169.  
  170. Boolean CApp::ObeyCommand(
  171.     CommandT inCommand,
  172.     void *ioParam)
  173. {
  174.     Boolean    cmdHandled = true;
  175.     
  176.     switch (inCommand)
  177.     {
  178.         case cmd_DropMode:
  179.         {
  180.             mDropMode = !mDropMode;
  181.             SetUpdateCommandStatus(true);
  182.             break;
  183.         }
  184.         
  185.         case cmd_Preferences:
  186.         {
  187.             CPrefsWindow *pw = (CPrefsWindow *)LWindow::CreateWindow(WIND_Preferences, this);
  188.             pw->Show();
  189.             break;
  190.         }
  191.         
  192.         default:
  193.             cmdHandled = LDocApplication::ObeyCommand(inCommand, ioParam);
  194.             break;
  195.     }
  196.     
  197.     return cmdHandled;
  198. }
  199.  
  200.  
  201. void CApp::FindCommandStatus(
  202.     CommandT    inCommand,
  203.     Boolean        &outEnabled,
  204.     Boolean        &outUsesMark,
  205.     Char16        &outMark,
  206.     Str255        outName)
  207. {
  208.     outUsesMark = false;
  209.     
  210.     if (sBusy)
  211.         outEnabled = false;
  212.     else
  213.         switch (inCommand)
  214.         {
  215.             case cmd_DropMode:
  216.                 outEnabled = true;
  217.                 outUsesMark = true;
  218.                 outMark = mDropMode ? checkMark:noMark;
  219.                 break;
  220.             
  221.             case cmd_Preferences:
  222.                 outEnabled = true;
  223.                 break;
  224.             
  225.             default:
  226.                 LDocApplication::FindCommandStatus(inCommand, outEnabled, outUsesMark,
  227.                         outMark, outName);
  228.                 break;
  229.         }
  230. }
  231.  
  232.  
  233. /* CApp::DoAEOpenOrPrintDoc
  234.  
  235.     Overridden from LDocApplication because we may want to quit afterwards.
  236. */
  237. void CApp::DoAEOpenOrPrintDoc(
  238.     const AppleEvent &inAppleEvent,
  239.     AppleEvent& /* outAEReply */,
  240.     Int32 inAENumber)
  241. {
  242.     AEDescList docList;
  243.     OSErr err = ::AEGetParamDesc(&inAppleEvent, keyDirectObject,
  244.                             typeAEList, &docList);
  245.     ThrowIfOSErr_(err);
  246.     
  247.     Int32 numDocs;
  248.     err = ::AECountItems(&docList, &numDocs);
  249.     ThrowIfOSErr_(err);
  250.     
  251.     for (Int32 i = 1; i <= numDocs; i++)
  252.     {
  253.         AEKeyword    theKey;
  254.         DescType    theType;
  255.         FSSpec        theFileSpec;
  256.         Size        theSize;
  257.         err = ::AEGetNthPtr(&docList, i, typeFSS, &theKey, &theType,
  258.                             (Ptr) &theFileSpec, sizeof(FSSpec), &theSize);
  259.         ThrowIfOSErr_(err);
  260.         
  261.         if (inAENumber == ae_OpenDoc)
  262.         {
  263.             OpenDocument(&theFileSpec);
  264.         }
  265.         else
  266.         {
  267.                 // let the user know we don't do printing in this app
  268.             ::StopAlert(ALRT_WeDontPrint, nil);
  269.         }
  270.     }
  271.     
  272.     ::AEDisposeDesc(&docList);
  273.     
  274.         // if we are in drop mode, get outta here
  275.     if (mDropMode)
  276.         DoQuit();
  277. }
  278.  
  279.  
  280. void CApp::OpenDocument(
  281.     FSSpec *inMacFSSpec)
  282. {
  283.     Int16 errStrIndex;
  284.     
  285.     try
  286.     {
  287.         errStrIndex = err_Window;
  288.         
  289.         if (mDropMode && mPrefsHdl != nil)
  290.         {
  291.                 // just start making the movie
  292.             MovieMakinRec params;
  293.             params.width = (*mPrefsHdl)->width;
  294.             params.height = (*mPrefsHdl)->height;
  295.             params.srcSpec = *inMacFSSpec;
  296.             
  297.             params.tileSpec = *inMacFSSpec;
  298.             unsigned char charspace = 31 - (*mPrefsHdl)->tileSuffix[0];
  299.             if (params.tileSpec.name[0] > charspace)
  300.                 params.tileSpec.name[0] = charspace;
  301.             ConcatPStr(params.tileSpec.name, (*mPrefsHdl)->tileSuffix);
  302.  
  303.             params.destSpec = *inMacFSSpec;
  304.             charspace = 31 - (*mPrefsHdl)->movieSuffix[0];
  305.             if (params.destSpec.name[0] > charspace)
  306.                 params.destSpec.name[0] = charspace;
  307.             ConcatPStr(params.destSpec.name, (*mPrefsHdl)->movieSuffix);
  308.             
  309.             params.codec = (*mPrefsHdl)->codec;
  310.             params.spatialQuality = (*mPrefsHdl)->spatialQuality;
  311.             params.depth = (*mPrefsHdl)->depth;
  312.             
  313.             ListenToMessage(msg_MakeMovie, ¶ms);
  314.         }
  315.         else
  316.         {
  317.                 // put up a window for editing movie making parameters
  318.             CPict2VRWindow *p2vr = (CPict2VRWindow *)LWindow::CreateWindow(WIND_Pict2VR, this);
  319.             p2vr->AddListener(this);
  320.             p2vr->SetPictFile(inMacFSSpec);
  321.         }
  322.     }
  323.     catch (ExceptionCode err)
  324.     {
  325.         ReportError(err, err_Window);
  326.     }
  327.     
  328.         // drop mode leaves the menu bar inactive
  329.     if (mDropMode)
  330.         UpdateMenus();
  331. }
  332.  
  333. void CApp::StartUp()
  334. {
  335.     ChooseDocument();
  336. }
  337.  
  338. void CApp::ChooseDocument()
  339. {
  340.     StandardFileReply macFileReply;
  341.     SFTypeList typeList;
  342.     
  343.     UDesktop::Deactivate();
  344.     typeList[0] = 'PICT';
  345.     ::StandardGetFile(nil, 1, typeList, &macFileReply);
  346.     UDesktop::Activate();
  347.     if (macFileReply.sfGood)
  348.     {
  349.         OpenDocument(&macFileReply.sfFile);
  350.     }
  351. }
  352.  
  353.  
  354. /* CApp::ProgressEvents
  355.  
  356.     An event processing function necessary because the one implemented in
  357.     LApplication does things we dont want such as changing the cursor.
  358.     This one is useful for processing events during lengthy processes
  359.     (and there is a spinning cursor and a modal window in front).
  360. */
  361. void CApp::ProgressEvents()
  362. {
  363.     EventRecord macEvent;
  364.  
  365.     SetUpdateCommandStatus(false);
  366.     Boolean    gotEvent;
  367.     Int16 count = 0;
  368.     
  369.     do
  370.     {
  371.         gotEvent = ::WaitNextEvent(everyEvent, &macEvent, 0, mMouseRgnH);
  372.         
  373.         if (LAttachable::ExecuteAttachments(msg_Event, &macEvent))
  374.         {
  375.             if (gotEvent)
  376.                 DispatchEvent(macEvent);
  377.             else
  378.                 UseIdleTime(macEvent);
  379.         }
  380.     
  381.         LPeriodical::DevoteTimeToRepeaters(macEvent);
  382.         
  383.         if (GetUpdateCommandStatus())
  384.             UpdateMenus();
  385.     } while (gotEvent && ++count < 3); // do not hand over too much time
  386. }
  387.  
  388.  
  389. // ======================================
  390. // constants and statics for movie making
  391.  
  392. Boolean CApp::sCancelled;
  393. LWindow *CApp::sProgressWindow = nil;
  394. Boolean CApp::sBusy = false;
  395.  
  396. const PaneIDT Button_Stop = 'stop';
  397. const PaneIDT Caption_Proc = 'proc';
  398. const PaneIDT Caption_Message = 'mess';
  399.  
  400. const ResIDT WIND_Progress = 207;
  401.  
  402. // ======================================
  403.  
  404. void CApp::ListenToMessage(
  405.     MessageT inMessage,
  406.     void *ioParam)
  407. {
  408.     switch (inMessage)
  409.     {
  410.             // note: one could conceivably tell the app to make a movie
  411.             // WHILE it is making one. this would work, except that the
  412.             // newly dropped one will be completed before the original is
  413.             // processed. this does not include numbers of PICTs dropped
  414.             // on the app at once in the Finder
  415.         case msg_MakeMovie:
  416.         {
  417.                 // the make movie message includes parameters for making the movie
  418.             MovieMakinPtr mmp = (MovieMakinPtr)ioParam;
  419.             
  420.             Str255 procStr;
  421.             ::GetIndString(procStr, STRx_Progress, str_Making);
  422.                 
  423.                 // create a path name that fits into a Str255 minus the above string
  424.             Str255 moviePathStr;
  425.             GetFullPathName(&mmp->destSpec, moviePathStr, sizeof (Str255) - procStr[0]);
  426.             
  427.             try
  428.             {
  429.                     // prepare progress stuff
  430.                 sCancelled = false;
  431.                 sBusy = true;
  432.                 SetUpdateCommandStatus(true);
  433.                 UpdateMenus();
  434.                 sProgressWindow = LWindow::CreateWindow(WIND_Progress, this);
  435.                 ThrowIfNil_(sProgressWindow);
  436.                 
  437.                     // set the main progress description string
  438.                 ConcatPStr(procStr, moviePathStr);
  439.                 SetSizedDescriptor(sProgressWindow, Caption_Proc, procStr);
  440.                 
  441.                     // listen to the stop button - provides both mouse and keyboard
  442.                     // initiated user cancellation
  443.                 LButton *button;
  444.                 button = (LButton *)sProgressWindow->FindPaneByID(Button_Stop);
  445.                 if (button != nil)
  446.                     button->AddListener(this);
  447.                 
  448.                     // decide if we are replacing files
  449.                 Boolean replaceFiles = false;
  450.                 if (mPrefsHdl != nil)
  451.                     replaceFiles = (*mPrefsHdl)->replaceFiles;
  452.                 
  453.                     // finally, make the movie!
  454.                 CBeachBall::StartSpinningTask(5);
  455.                 Boolean completed = CMovieMaker::MakeAMovie(
  456.                     replaceFiles,
  457.                     mmp->srcSpec, mmp->tileSpec, mmp->destSpec,
  458.                     mmp->width, mmp->height, 
  459.                     mmp->pan, mmp->tilt, mmp->zoom,
  460.                     mmp->codec, mmp->spatialQuality, mmp->depth, MovieProgressProc);
  461.                 CBeachBall::StopSpinningTask();
  462.                 
  463.                 delete sProgressWindow;
  464.                 sProgressWindow = nil;
  465.                 
  466.                     // let the caller know how things went
  467.                 mmp->completed = completed;
  468.             }
  469.             catch (ExceptionCode err)
  470.             {
  471.                 mmp->completed = false;
  472.                 
  473.                     // the only exception that can make it here is to fail
  474.                     // while creating the progress window
  475.                     // all other exceptions are caught by CMovieMaker::MakeAMovie
  476.                 if (err != Exception_UserCancelled)
  477.                     ReportError(err, err_Window);
  478.             }
  479.             
  480.             sBusy = false;
  481.             UpdateMenus();
  482.             break;
  483.         }
  484.         
  485.         case Button_Stop:
  486.             sCancelled = true;
  487.             break;
  488.     }
  489. }
  490.  
  491. /* CApp::MovieProgressProc
  492.  
  493.     Called during processing. Gets events handled, messages displayed and
  494.     user cancellation reported.
  495. */
  496. Boolean CApp::MovieProgressProc(
  497.     StringPtr inMessage)
  498. {
  499.     if (inMessage != nil)
  500.     {
  501.         LPane *messageCaption = sProgressWindow->FindPaneByID(Caption_Message);
  502.         messageCaption->SetDescriptor(inMessage);
  503.         messageCaption->UpdatePort();
  504.     }
  505.     
  506.     gApp->ProgressEvents();
  507.     
  508.     return sCancelled;
  509. }
  510.  
  511. /* CApp::BugUserTilSwitchedIn
  512.  
  513.     Use the notification manager to let the user know they should switch in.
  514.     Returns once this has happened.
  515.     
  516.     Useful for waiting to put up alerts during long processes where the possibility
  517.     of the user having switched out is an issue.
  518. */
  519. void CApp::BugUserTilSwitchedIn()
  520. {
  521.     if (!IsOnDuty())
  522.     {
  523.         NMRec note;
  524.         OSErr nmErr;
  525.         Handle sicnH = ::GetResource('SICN', 12000);
  526.         
  527.         if (sicnH)
  528.         {
  529.             ::HNoPurge(sicnH);
  530.             ::DetachResource(sicnH);
  531.         }
  532.         
  533.         note.qType = nmType;
  534.         note.nmMark = 1;
  535.         note.nmIcon = sicnH;
  536.         note.nmSound = (Handle) -1;
  537.         note.nmStr = nil;
  538.         note.nmResp = nil;
  539.         note.nmRefCon = 0;
  540.         
  541.         if ((nmErr = ::NMInstall(¬e)) == noErr)
  542.         {
  543.             while (!IsOnDuty())
  544.             {
  545.                 ProgressEvents();
  546.             }
  547.             nmErr = ::NMRemove(¬e);
  548.         }
  549.         
  550.         if (sicnH != nil)
  551.             ::DisposeHandle(sicnH);
  552.     }
  553. }
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.